import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;

public class FuzzTable {
	
	private static FuzzTable instance = null;
	private HashMap<Integer, ArrayList<String>> fuzzTable = null;
	private HashMap<Integer, ArrayList<String>> attackTable = null;

	public static FuzzTable getInstance() throws IOException, DetectorException{
		if (instance==null)
			instance = new FuzzTable();
		return instance;
	}
	
	protected FuzzTable() throws IOException, DetectorException{
		fuzzTable = new HashMap<Integer, ArrayList<String>>();
		attackTable = new HashMap<Integer, ArrayList<String>>();
		fuzzTable = BuildValuesTableFromFile("fuzzTable.txt");
		attackTable = BuildValuesTableFromFile("attackTable.txt");
	}
	
	private HashMap<Integer, ArrayList<String>> BuildValuesTableFromFile(String fileName) throws IOException, DetectorException{
		/*The file should be a text file having the following structure
		 * key1
		 * (value1,value2,value3...)
		 * key2
		 * (value1,value2,...)
		 */
		HashMap<Integer, ArrayList<String>> temp = new HashMap<Integer, ArrayList<String>>();
		BufferedReader br = new BufferedReader(new FileReader(fileName));
		String currLine = br.readLine();
		String formerLine = null;
		String values;
		ArrayList<String> arr ;
		while (currLine!=null){
			if (currLine.startsWith("(")){//values
				if (formerLine!=null){
					arr =temp.get(formerLine.hashCode());
					values = currLine.substring(currLine.indexOf('(')+1,currLine.lastIndexOf(')'));
					StringTokenizer st = new StringTokenizer(values,",");
					while (st.hasMoreTokens())
						arr.add(st.nextToken());
					temp.put(formerLine.hashCode(), arr);
					formerLine=currLine;
					currLine = br.readLine();
				}
				else{
					throw (new DetectorException("Fuzzer Error. Input file problem"));
				}
			}
			else{//key
				temp.put(currLine.hashCode(), new ArrayList<String>());
				formerLine = currLine;
				currLine = br.readLine();
			}
		}
		return temp;
	}

	public HashMap<Integer, ArrayList<String>> getFuzzTable() {
		return fuzzTable;
	}
	public HashMap<Integer, ArrayList<String>> getAttackTable() {
		return attackTable;
	}
}
